home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 2
/
Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso
/
Aminet
/
comm
/
term
/
term34Source.lha
/
termSerial.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-16
|
36KB
|
1,904 lines
/*
** termSerial.c
**
** Serial driver support routines
**
** Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
** All Rights Reserved
*/
#include "termGlobal.h"
/* The quantum of bytes to be read from the serial port,
* to be fed to the terminal emulation monster. This is where
* two worlds collide; first there is the idea to process as
* much data as there is currently available for reasons
* of efficiency. Second there is a problem caused by the
* fact that terminal emulation may not be able to
* output text as fast as new data comes in. Terminal and
* serial input will be blocked until all data is processed,
* so the quantum should be pretty small to avoid unnecessary
* processing delays.
*/
/* Local copy of serial driver name and unit number. */
STATIC UBYTE SerialDevice[40];
STATIC LONG UnitNumber = -1;
/* SetFlags(struct IOExtSer *SomeRequest):
*
* Set the contents of a serial device request according
* to the current configuration settings.
*/
VOID __regargs
SetFlags(struct IOExtSer *SomeRequest)
{
/* Remember new baud rate. */
DTERate = Config -> SerialConfig -> BaudRate;
SomeRequest -> io_Baud = Config -> SerialConfig -> BaudRate;
SomeRequest -> io_BrkTime = Config -> SerialConfig -> BreakLength;
SomeRequest -> io_ReadLen = Config -> SerialConfig -> BitsPerChar;
SomeRequest -> io_WriteLen = Config -> SerialConfig -> BitsPerChar;
SomeRequest -> io_StopBits = Config -> SerialConfig -> StopBits;
SomeRequest -> io_ExtFlags &= ~(SEXTF_MSPON | SEXTF_MARK);
SomeRequest -> io_SerFlags &= ~(SERF_PARTY_ON | SERF_PARTY_ODD | SERF_7WIRE | SERF_RAD_BOOGIE);
switch(Config -> SerialConfig -> Parity)
{
case PARITY_EVEN:
SomeRequest -> io_SerFlags |= SERF_PARTY_ON;
break;
case PARITY_ODD:
SomeRequest -> io_SerFlags |= SERF_PARTY_ON | SERF_PARTY_ODD;
break;
case PARITY_MARK:
SomeRequest -> io_SerFlags |= SERF_PARTY_ON;
SomeRequest -> io_ExtFlags |= SEXTF_MSPON | SEXTF_MARK;
break;
case PARITY_SPACE:
SomeRequest -> io_SerFlags |= SERF_PARTY_ON;
SomeRequest -> io_ExtFlags |= SEXTF_MSPON;
break;
}
if(Config -> SerialConfig -> HandshakingProtocol != HANDSHAKING_NONE)
SomeRequest -> io_SerFlags |= SERF_7WIRE;
if(Config -> SerialConfig -> HighSpeed)
SomeRequest -> io_SerFlags |= SERF_RAD_BOOGIE;
if(Config -> SerialConfig -> Shared)
SomeRequest -> io_SerFlags |= SERF_SHARED;
SomeRequest -> io_SerFlags |= SERF_XDISABLED;
}
/* GetFlags(struct Configuration *Config,struct IOExtSer *SomeRequest):
*
* Update configuration with serial settings.
*/
VOID __regargs
GetFlags(struct Configuration *Config,struct IOExtSer *SomeRequest)
{
Config -> SerialConfig -> BaudRate = SomeRequest -> io_Baud;
Config -> SerialConfig -> BreakLength = SomeRequest -> io_BrkTime;
Config -> SerialConfig -> BitsPerChar = SomeRequest -> io_ReadLen;
Config -> SerialConfig -> BitsPerChar = SomeRequest -> io_WriteLen;
Config -> SerialConfig -> StopBits = SomeRequest -> io_StopBits;
if(SomeRequest -> io_SerFlags & SERF_PARTY_ON)
{
if(SomeRequest -> io_SerFlags & SERF_PARTY_ODD)
Config -> SerialConfig -> Parity = PARITY_ODD;
else
{
if(SomeRequest -> io_ExtFlags & SEXTF_MSPON)
{
if(SomeRequest -> io_ExtFlags & SEXTF_MARK)
Config -> SerialConfig -> Parity = PARITY_MARK;
else
Config -> SerialConfig -> Parity = PARITY_SPACE;
}
}
}
else
Config -> SerialConfig -> Parity = PARITY_NONE;
if(SomeRequest -> io_SerFlags & SERF_7WIRE)
Config -> SerialConfig -> HandshakingProtocol = HANDSHAKING_RTSCTS;
else
Config -> SerialConfig -> HandshakingProtocol = HANDSHAKING_NONE;
if(SomeRequest -> io_SerFlags & SERF_RAD_BOOGIE)
Config -> SerialConfig -> HighSpeed = TRUE;
else
Config -> SerialConfig -> HighSpeed = FALSE;
if(SomeRequest -> io_SerFlags & SERF_SHARED)
Config -> SerialConfig -> Shared = TRUE;
else
Config -> SerialConfig -> Shared = FALSE;
SomeRequest -> io_SerFlags |= SERF_XDISABLED;
}
/* CallMenu(STRPTR Name,ULONG Code):
*
* Call a menu function either through the name of the corresponding
* menu item or a menu number.
*/
STATIC VOID __inline
CallMenu(STRPTR Name,ULONG Code)
{
WORD MenuNum = -1,Item = 0,Sub = 0,i;
/* Are we to look for a name? */
if(Name)
{
WORD Len = strlen(Name);
/* Scan the menu list... */
for(i = 0 ; TermMenu[i] . nm_Type != NM_END ; i++)
{
switch(TermMenu[i] . nm_Type)
{
case NM_TITLE:
MenuNum++;
Item = Sub = 0;
break;
case NM_ITEM:
Sub = 0;
break;
}
/* Did we get a valid name string? */
if(TermMenu[i] . nm_Label != NM_BARLABEL)
{
/* Does the name match our template? */
if(!Strnicmp(TermMenu[i] . nm_Label,Name,Len))
{
struct MenuItem *MenuItem = ItemAddress(Menu,FULLMENUNUM(MenuNum,Item,Sub));
if(MenuItem)
HandleMenuCode((ULONG)TermMenu[i] . nm_UserData,NULL);
break;
}
}
switch(TermMenu[i] . nm_Type)
{
case NM_ITEM:
Item++;
break;
case NM_SUB:
Sub++;
break;
}
}
}
else
{
WORD TheMenu = Code % 100,
TheItem = (Code / 100) % 100,
TheSub = Code / 10000;
/* Scan the menu list... */
for(i = 0 ; TermMenu[i] . nm_Type != NM_END ; i++)
{
switch(TermMenu[i] . nm_Type)
{
case NM_TITLE:
MenuNum++;
Item = Sub = 0;
break;
case NM_ITEM:
Sub = 0;
break;
}
/* Is it the menu number we want? */
if(TheMenu == MenuNum && TheItem == Item && TheSub == Sub)
{
if(TermMenu[i] . nm_Label != NM_BARLABEL)
{
struct MenuItem *MenuItem = ItemAddress(Menu,FULLMENUNUM(MenuNum,Item,Sub));
if(MenuItem)
HandleMenuCode((ULONG)TermMenu[i] . nm_UserData,NULL);
}
break;
}
switch(TermMenu[i] . nm_Type)
{
case NM_ITEM:
Item++;
break;
case NM_SUB:
Sub++;
break;
}
}
}
}
/* SerialCommand(STRPTR String):
*
* Send a command string to the serial line and
* interprete the control sequences.
*/
VOID __regargs
SerialCommand(STRPTR String)
{
BYTE (* __regargs SendLineLocal)(register STRPTR,register LONG);
LONG Count = 0,i,Len = strlen(String);
BYTE GotControl = FALSE,
GotEscape = FALSE,
OldStatus;
SendLineLocal = SendLine;
/* Scan the string. */
for(i = 0 ; i < Len ; i++)
{
/* We are looking for plain characters
* and the control ('\') and escape
* ('^') characters.
*/
if(!GotControl && !GotEscape)
{
/* Got a control character,
* the next byte will probably be
* a command sequence.
*/
if(String[i] == '\\')
{
GotControl = TRUE;
continue;
}
/* Got an escape character,
* the next byte will be some
* kind of control character
* (such as XON, XOF, bell, etc.).
*/
if(String[i] == '^')
{
GotEscape = TRUE;
continue;
}
/* This tells us to wait another
* second before continuing with
* the scanning.
*/
if(String[i] == '~')
{
if(Count)
{
(*SendLineLocal)(SharedBuffer,Count);
Count = 0;
}
WaitTime(0,MILLION / 2);
HandleSerial();
continue;
}
/* Stuff the character into the
* buffer.
*/
SharedBuffer[Count++] = String[i];
}
else
{
/* Convert the character to a control
* style character (^C, etc.).
*/
if(GotEscape)
{
if(ToUpper(String[i]) >= 'A' && ToUpper(String[i]) <= '_')
SharedBuffer[Count++] = ToUpper(String[i]) - '@';
else
SharedBuffer[Count++] = String[i];
GotEscape = FALSE;
}
/* The next character represents a command. */
if(GotControl)
{
switch(ToUpper(String[i]))
{
/* Fall back to default send mode. */
case '0':
if(Count)
{
(*SendLineLocal)(SharedBuffer,Count);
Count = 0;
}
SendLineLocal = SendLine;
break;
/* Select `direct' send mode. */
case '1':
if(Count)
{
(*SendLineLocal)(SharedBuffer,Count);
Count = 0;
}
SendLineLocal = SendLineSimple;
break;
/* Select `echo' send mode. */
case '2':
if(Count)
{
(*SendLineLocal)(SharedBuffer,Count);
Count = 0;
}
if(Config -> ClipConfig -> SendTimeout)
SendLineLocal = SendLineEcho;
else
SendLineLocal = SendLineSimple;
break;
/* Select `any echo' send mode. */
case '3':
if(Count)
{
(*SendLineLocal)(SharedBuffer,Count);
Count = 0;
}
if(Config -> ClipConfig -> SendTimeout)
SendLineLocal = SendLineAnyEcho;
else
SendLineLocal = SendLineSimple;
break;
/* Select `prompt' send mode. */
case '4':
if(Count)
{
(*SendLineLocal)(SharedBuffer,Count);
Count = 0;
}
if(Config -> ClipConfig -> SendTimeout)
SendLineLocal = SendLinePrompt;
else
SendLineLocal = SendLineSimple;
break;
/* Select `delay' send mode. */
case '5':
if(Count)
{
(*SendLineLocal)(SharedBuffer,Count);
Count = 0;
}
if(Config -> ClipConfig -> LineDelay || Config -> ClipConfig -> CharDelay)
SendLineLocal = SendLineDelay;
else
SendLineLocal = SendLineSimple;
break;
/* Select `keyboard' send mode. */
case '6':
if(Count)
{
(*SendLineLocal)(SharedBuffer,Count);
Count = 0;
}
SendLineLocal = SendLineKeyDelay;
break;
/* Translate code. */
case '*':
i++;
while(i < Len && String[i] == ' ')
i++;
if(i < Len)
{
UBYTE DummyBuffer[5],j = 0,Char;
if(String[i] >= '0' && String[i] <= '9')
{
while(j < 3 && i < Len)
{
Char = String[i++];
if(Char >= '0' && Char <= '9')
DummyBuffer[j++] = Char;
else
{
i--;
break;
}
}
}
else
{
while(j < 4 && i < Len)
{
Char = ToLower(String[i++]);
if((Char >= '0' && Char <= '9') || (Char >= 'a' && Char <= 'z'))
DummyBuffer[j++] = Char;
else
{
i--;
break;
}
}
}
DummyBuffer[j] = 0;
SharedBuffer[Count++] = NameToCode(DummyBuffer);
}
i--;
break;
/* Execute an AmigaDOS command. */
case 'D':
if(!InRexx)
{
if(!WeAreBlocking)
{
BlockWindows();
SendAmigaDOSCommand(&String[i + 1]);
ReleaseWindows();
}
else
SendAmigaDOSCommand(&String[i + 1]);
}
return;
/* Execute an ARexx command. */
case 'A':
#ifdef USE_AREXX
if(!InRexx)
{
if(!WeAreBlocking)
{
BlockWindows();
SendARexxCommand(&String[i + 1]);
ReleaseWindows();
}
else
SendARexxCommand(&String[i + 1]);
}
#endif /* USE_AREXX */
return;
/* Add the control character ('\'). */
case '\\':
SharedBuffer[Count++] = '\\';
break;
/* This is a backspace. */
case 'B':
SharedBuffer[Count++] = '\b';
break;
/* This is a form feed. */
case 'F':
SharedBuffer[Count++] = '\f';
break;
/* This is a line feed. */
case 'N':
SharedBuffer[Count++] = '\n';
break;
/* Send the current password. */
case 'P':
if(Password[0])
{
if(Count)
{
(*SendLineLocal)(SharedBuffer,Count);
Count = 0;
}
(*SendLineLocal)(Password,strlen(Password));
}
break;
/* This is a carriage return. */
case 'R':
SharedBuffer[Count++] = '\r';
break;
/* This is a tab. */
case 'T':
SharedBuffer[Count++] = '\t';
break;
/* Send the current user name. */
case 'U':
if(UserName[0])
{
if(Count)
{
(*SendLineLocal)(SharedBuffer,Count);
Count = 0;
}
(*SendLineLocal)(UserName,strlen(UserName));
}
break;
/* Send a break across the serial line. */
case 'X':
if(Count)
{
(*SendLineLocal)(SharedBuffer,Count);
Count = 0;
}
if(WriteRequest)
{
OldStatus = Status;
Status = STATUS_BREAKING;
WriteRequest -> IOSer . io_Command = SDCMD_BREAK;
DoIO(WriteRequest);
Status = OldStatus;
}
break;
/* Feed the contents of the
* clipboard into the input
* stream.
*/
case 'I':
if(Count)
(*SendLineLocal)(SharedBuffer,Count);
Count = LoadClip(SharedBuffer,256);
break;
/* Send a string to the clipboard. */
case 'G':
if(String[i + 1])
SaveClip(&String[i + 1],strlen(&String[i + 1]));
return;
/* Send a string to the clipboard. */
case 'H':
if(String[i + 1])
AddClip(&String[i + 1],strlen(&String[i + 1]));
return;
/* Produce the escape character. */
case 'E':
SharedBuffer[Count++] = ESC;
break;
/* Call a menu item. */
case 'C':
i++;
/* Scan for a menu number or
* a single quote...
*/
while(i < Len)
{
if(String[i] >= '0' && String[i] <= '9')
break;
if(String[i] == '\'')
break;
if(String[i] != ' ')
break;
i++;
}
if(i < Len)
{
UBYTE DummyBuffer[256];
/* Did we get a quote? */
if(String[i] == '\'')
{
LONG Start = ++i;
if(String[Start])
{
WORD Length;
while(i < Len)
{
if(String[i] != '\'')
i++;
else
break;
}
if(String[i] == '\'')
Length = i - Start;
else
Length = i - Start + 1;
memcpy(DummyBuffer,&String[Start],Length);
DummyBuffer[Length] = 0;
CallMenu(DummyBuffer,0);
}
}
else
{
if(String[i] >= '0' && String[i] <= '9')
{
LONG Start = i,Length;
while(i < Len)
{
if(String[i] >= '0' && String[i] <= '9')
i++;
else
break;
}
if(i == Start)
Length = 1;
else
Length = i - Start;
memcpy(DummyBuffer,&String[Start],Length);
DummyBuffer[Length] = 0;
CallMenu(NULL,Atol(DummyBuffer));
}
}
}
break;
/* Stuff the character into the buffer. */
default:
SharedBuffer[Count++] = String[i];
break;
}
GotControl = FALSE;
}
}
/* If the buffer is full, release it. */
if(Count == 256)
{
(*SendLineLocal)(SharedBuffer,Count);
Count = 0;
}
}
if(Count)
(*SendLineLocal)(SharedBuffer,Count);
}
/* SerWrite(APTR Buffer,LONG Size):
*
* Send a number of bytes across the serial line.
*/
VOID __regargs
SerWrite(APTR Buffer,LONG Size)
{
if(Size < 0)
Size = strlen(Buffer);
if(WriteRequest && Size)
{
STATIC UBYTE TranslateData[512];
/* xpr wants to see the data before it is
* transferred.
*/
if(XProtocolBase && (TransferBits & XPRS_USERMON))
{
if(Size = XProtocolUserMon(XprIO,Buffer,Size,Size))
{
if(SendTable)
{
struct TranslationHandle Handle;
/* Set up for buffer translation. */
TranslateSetup(&Handle,Buffer,Size,TranslateData,512,SendTable);
/* Full or half duplex? */
if(Config -> SerialConfig -> Duplex == DUPLEX_FULL)
{
/* Process the data... */
while(Size = TranslateBuffer(&Handle))
{
WriteRequest -> IOSer . io_Command = CMD_WRITE;
WriteRequest -> IOSer . io_Data = TranslateData;
WriteRequest -> IOSer . io_Length = Size;
/* ...and send it. */
DoIO(WriteRequest);
BytesOut += Size;
}
}
else
{
if(Marking)
DropMarker();
ClearCursor();
while(Size = TranslateBuffer(&Handle))
{
WriteRequest -> IOSer . io_Command = CMD_WRITE;
WriteRequest -> IOSer . io_Data = TranslateData;
WriteRequest -> IOSer . io_Length = Size;
/* Process the data while it is transferred. */
SendIO(WriteRequest);
ConProcess(Buffer,Size);
WaitIO(WriteRequest);
BytesOut += Size;
}
DrawCursor();
}
}
else
{
WriteRequest -> IOSer . io_Command = CMD_WRITE;
WriteRequest -> IOSer . io_Data = Buffer;
WriteRequest -> IOSer . io_Length = Size;
/* If full duplex is enabled, send the entire
* buffer without processing.
*/
if(Config -> SerialConfig -> Duplex == DUPLEX_FULL)
DoIO(WriteRequest);
else
{
/* Process the data while it is transferred. */
SendIO(WriteRequest);
if(Marking)
DropMarker();
ClearCursor();
ConProcess(Buffer,Size);
DrawCursor();
WaitIO(WriteRequest);
}
BytesOut += Size;
}
}
}
else
{
if(SendTable)
{
struct TranslationHandle Handle;
/* Set up for buffer translation. */
TranslateSetup(&Handle,Buffer,Size,TranslateData,512,SendTable);
/* Full or half duplex? */
if(Config -> SerialConfig -> Duplex == DUPLEX_FULL)
{
/* Process the data... */
while(Size = TranslateBuffer(&Handle))
{
WriteRequest -> IOSer . io_Command = CMD_WRITE;
WriteRequest -> IOSer . io_Data = TranslateData;
WriteRequest -> IOSer . io_Length = Size;
/* ...and send it. */
DoIO(WriteRequest);
BytesOut += Size;
}
}
else
{
if(Marking)
DropMarker();
ClearCursor();
while(Size = TranslateBuffer(&Handle))
{
WriteRequest -> IOSer . io_Command = CMD_WRITE;
WriteRequest -> IOSer . io_Data = TranslateData;
WriteRequest -> IOSer . io_Length = Size;
/* Process the data while it is transferred. */
SendIO(WriteRequest);
ConProcess(Buffer,Size);
WaitIO(WriteRequest);
BytesOut += Size;
}
DrawCursor();
}
}
else
{
WriteRequest -> IOSer . io_Command = CMD_WRITE;
WriteRequest -> IOSer . io_Data = Buffer;
WriteRequest -> IOSer . io_Length = Size;
/* If full duplex is enabled, send the entire
* buffer without processing.
*/
if(Config -> SerialConfig -> Duplex == DUPLEX_FULL)
DoIO(WriteRequest);
else
{
/* Process the data while it is transferred. */
SendIO(WriteRequest);
if(Marking)
DropMarker();
ClearCursor();
ConProcess(Buffer,Size);
DrawCursor();
WaitIO(WriteRequest);
}
BytesOut += Size;
}
}
}
}
/* RestartSerial():
*
* Restart read/write activity on the serial line.
*/
VOID
RestartSerial()
{
if(ReadRequest)
{
ReadRequest -> IOSer . io_Command = CMD_READ;
ReadRequest -> IOSer . io_Data = ReadBuffer;
ReadRequest -> IOSer . io_Length = 1;
ClrSignal(SIG_SERIAL);
SendIO(ReadRequest);
}
}
/* ClearSerial():
*
* Terminate all read/write activity on the serial line.
*/
VOID
ClearSerial()
{
if(ReadRequest)
{
if(!CheckIO(ReadRequest))
AbortIO(ReadRequest);
WaitIO(ReadRequest);
}
if(WriteRequest)
{
WriteRequest -> IOSer . io_Command = CMD_FLUSH;
DoIO(WriteRequest);
WriteRequest -> IOSer . io_Command = CMD_CLEAR;
DoIO(WriteRequest);
}
}
/* DropDTR():
*
* Drop the data terminal ready signal (i.e. close, wait a bit
* and then reopen the serial drive).
*/
BYTE
DropDTR()
{
/* Finish all serial read activity. */
ClearSerial();
/* Do we have any channels to work with? */
if(ReadRequest && WriteRequest)
{
/* Close the device. */
CloseDevice(ReadRequest);
/* Wait a bit. */
WaitTime(1,0);
/* Set up the original configuration data. */
SetFlags(ReadRequest);
ReadRequest -> io_RBufLen = Config -> SerialConfig -> SerialBufferSize;
/* Reopen the driver. */
if(!OpenDevice(Config -> SerialConfig -> SerialDevice,Config -> SerialConfig -> UnitNumber,ReadRequest,0))
{
struct MsgPort *WritePort = WriteRequest -> IOSer . io_Message . mn_ReplyPort;
/* Fill in the rest. */
CopyMem(ReadRequest,WriteRequest,sizeof(struct IOExtSer));
WriteRequest -> IOSer . io_Message . mn_ReplyPort = WritePort;
WriteRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
SetFlags(WriteRequest);
DoIO(WriteRequest);
/* Restart read activity. */
ReadRequest -> IOSer . io_Command = CMD_READ;
ReadRequest -> IOSer . io_Data = ReadBuffer;
ReadRequest -> IOSer . io_Length = 1;
ClrSignal(SIG_SERIAL);
SendIO(ReadRequest);
return(TRUE);
}
else
DeleteSerial();
}
else
{
DeleteSerial();
return(TRUE);
}
return(FALSE);
}
/* DeleteSerial():
*
* Close the serial device and release all associated
* resources.
*/
VOID
DeleteSerial()
{
BYTE Closed = FALSE;
if(ReadRequest)
{
if(ReadRequest -> IOSer . io_Device)
{
if(!Config -> SerialConfig -> Shared)
{
ReadRequest -> IOSer . io_Command = CMD_RESET;
DoIO(ReadRequest);
}
CloseDevice(ReadRequest);
Closed = TRUE;
}
DeleteIORequest(ReadRequest);
ReadRequest = NULL;
}
if(WriteRequest)
{
if(WriteRequest -> IOSer . io_Device && !Closed)
{
if(!Config -> SerialConfig -> Shared && ReadRequest)
{
ReadRequest -> IOSer . io_Command = CMD_RESET;
DoIO(ReadRequest);
}
CloseDevice(WriteRequest);
}
if(WriteRequest -> IOSer . io_Message . mn_ReplyPort)
DeleteMsgPort(WriteRequest -> IOSer . io_Message . mn_ReplyPort);
DeleteIORequest(WriteRequest);
WriteRequest = NULL;
}
if(ReadPort)
{
DeleteMsgPort(ReadPort);
ReadPort = NULL;
}
if(ReadBuffer)
{
FreeVec(ReadBuffer);
ReadBuffer = NULL;
}
if(HostReadBuffer)
{
FreeVec(HostReadBuffer);
HostReadBuffer = NULL;
}
if(StripBuffer)
{
FreeVec(StripBuffer);
StripBuffer = NULL;
}
if(OwnDevUnitBase && SerialDevice[0] && UnitNumber != -1)
{
FreeDevUnit(SerialDevice,UnitNumber);
SerialDevice[0] = 0;
UnitNumber = -1;
}
}
/* GetSerialError(LONG Error,BYTE *Reset):
*
* Return an error message for each possible serial device error.
*/
STRPTR
GetSerialError(LONG Error,BYTE *Reset)
{
if(Reset)
*Reset = FALSE;
switch(Error)
{
case IOERR_BADLENGTH:
case IOERR_BADADDRESS:
case IOERR_SELFTEST:
case IOERR_OPENFAIL:
return(LocaleString(MSG_SERIAL_OPENFAILURE_TXT));
case SerErr_DevBusy:
return(LocaleString(MSG_SERIAL_ERROR_DEVBUSY_TXT));
case SerErr_BaudMismatch:
if(Reset)
*Reset = TRUE;
return(LocaleString(MSG_SERIAL_ERROR_BAUDMISMATCH_TXT));
case SerErr_BufErr:
if(Reset)
*Reset = TRUE;
return(LocaleString(MSG_SERIAL_ERROR_BUFERR_TXT));
case SerErr_InvParam:
if(Reset)
*Reset = TRUE;
return(LocaleString(MSG_SERIAL_ERROR_INVPARAM_TXT));
case SerErr_LineErr:
return(LocaleString(MSG_SERIAL_ERROR_LINEERR_TXT));
case SerErr_ParityErr:
if(Reset)
*Reset = TRUE;
return(LocaleString(MSG_SERIAL_ERROR_PARITYERR_TXT));
case SerErr_TimerErr:
return(LocaleString(MSG_SERIAL_ERROR_TIMERERR_TXT));
case SerErr_BufOverflow:
if(Reset)
*Reset = TRUE;
return(LocaleString(MSG_SERIAL_ERROR_BUFOVERFLOW_TXT));
case SerErr_NoDSR:
return(LocaleString(MSG_SERIAL_ERROR_NODSR_TXT));
/* case SerErr_UnitBusy: */
case IOERR_UNITBUSY:
case 16:
return(LocaleString(MSG_SERIAL_ERROR_UNIT_BUSY_TXT));
default:
return(NULL);
}
}
/* CreateSerial():
*
* Create handles for the serial device and open it.
*/
STRPTR
CreateSerial()
{
struct MsgPort *WritePort;
/* If OwnDevUnit.library is available, try to lock
* the serial driver.
*/
Start: if(OwnDevUnitBase)
{
STRPTR Error;
/* Attempt to lock the device unit... */
if(Error = AttemptDevUnit(Config -> SerialConfig -> SerialDevice,Config -> SerialConfig -> UnitNumber,TermIDString,NULL))
{
/* Check for error type if any. */
if(!Strnicmp(Error,ODUERR_LEADCHAR,1))
SPrintf(SharedBuffer,LocaleString(MSG_SERIAL_ERROR_ACCESSING_TXT),Config -> SerialConfig -> SerialDevice,Config -> SerialConfig -> UnitNumber,&Error[1]);
else
SPrintf(SharedBuffer,LocaleString(MSG_SERIAL_DEVICE_IN_USE_TXT),Config -> SerialConfig -> SerialDevice,Config -> SerialConfig -> UnitNumber,Error);
SerialDevice[0] = 0;
UnitNumber = -1;
return(SharedBuffer);
}
else
{
strcpy(SerialDevice,Config -> SerialConfig -> SerialDevice);
UnitNumber = Config -> SerialConfig -> UnitNumber;
}
}
if(ReadBuffer = AllocVec(Config -> SerialConfig -> SerialBufferSize,MEMF_ANY))
{
if(StripBuffer = AllocVec(Config -> SerialConfig -> SerialBufferSize,MEMF_ANY))
{
if(XProtocolBase && (TransferBits & XPRS_HOSTNOWAIT))
HostReadBuffer = AllocVec(Config -> SerialConfig -> SerialBufferSize,MEMF_ANY);
else
HostReadBuffer = NULL;
if(ReadPort = (struct MsgPort *)CreateMsgPort())
{
if(ReadRequest = (struct IOExtSer *)CreateIORequest(ReadPort,sizeof(struct IOExtSer)))
{
LONG Error;
SetFlags(ReadRequest);
ReadRequest -> io_RBufLen = Config -> SerialConfig -> SerialBufferSize;
if(!(Error = OpenDevice(Config -> SerialConfig -> SerialDevice,Config -> SerialConfig -> UnitNumber,ReadRequest,0)))
{
if(WritePort = (struct MsgPort *)CreateMsgPort())
{
if(WriteRequest = (struct IOExtSer *)CreateIORequest(WritePort,sizeof(struct IOExtSer)))
{
CopyMem(ReadRequest,WriteRequest,sizeof(struct IOExtSer));
WriteRequest -> IOSer . io_Message . mn_ReplyPort = WritePort;
WriteRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
SetFlags(WriteRequest);
DoIO(WriteRequest);
/* If RTS/CTS (7 wire handshaking) is
* selected, have a look at the DSR
* line to see whether the modem
* connected is willing to support
* this handshaking mode.
*/
if(Config -> SerialConfig -> HandshakingProtocol == HANDSHAKING_RTSCTS_DSR)
{
Retry: WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
DoIO(WriteRequest);
/* If the line happens to
* be high, there is no
* DSR signal present.
*/
if(WriteRequest -> io_Status & CIAF_COMDSR)
{
if(MyEasyRequest(Window,LocaleString(MSG_SERIAL_NO_DSR_SIGNAL_TXT),LocaleString(MSG_SERIAL_RETRY_CANCEL_TXT)))
goto Retry;
else
{
DeleteSerial();
Config -> SerialConfig -> HandshakingProtocol = HANDSHAKING_NONE;
SerialMessage = LocaleString(MSG_SERIAL_NO_DSR_SIGNAL_HANDSHAKING_DISABLED_TXT);
goto Start;
}
}
}
ReadRequest -> IOSer . io_Command = CMD_READ;
ReadRequest -> IOSer . io_Data = ReadBuffer;
ReadRequest -> IOSer . io_Length = 1;
ClrSignal(SIG_SERIAL);
SendIO(ReadRequest);
return(NULL);
}
}
else
{
SerialMessage = NULL;
DeleteSerial();
return(LocaleString(MSG_SERIAL_FAILED_TO_CREATE_WRITE_PORT_TXT));
}
}
else
{
STRPTR String;
ReadRequest -> IOSer . io_Device = NULL;
DeleteSerial();
SerialMessage = NULL;
if(!(String = GetSerialError(Error,NULL)))
String = LocaleString(MSG_SERIAL_ERROR_DEVBUSY_TXT);
SPrintf(SharedBuffer,String,Config -> SerialConfig -> SerialDevice,Config -> SerialConfig -> UnitNumber);
return(SharedBuffer);
}
}
}
else
{
SerialMessage = NULL;
DeleteSerial();
return(LocaleString(MSG_SERIAL_FAILED_TO_CREATE_READ_PORT_TXT));
}
}
}
SerialMessage = NULL;
DeleteSerial();
return(LocaleString(MSG_SERIAL_NOT_ENOUGH_MEMORY_TXT));
}
/* ReconfigureSerial(struct Window *Window,struct SerialSettings *SerialConfig):
*
* Reconfigure the serial driver according to the new
* serial settings.
*/
BYTE
ReconfigureSerial(struct Window *Window,struct SerialSettings *SerialConfig)
{
BYTE Success = RECONFIGURE_NOCHANGE,
IsNew;
/* Are new settings to be installed or have they already
* been copied to the correct locations?
*/
if(SerialConfig)
{
if(memcmp(Config -> SerialConfig,SerialConfig,sizeof(struct SerialSettings)))
IsNew = TRUE;
else
IsNew = FALSE;
}
else
{
if(memcmp(Config -> SerialConfig,PrivateConfig -> SerialConfig,sizeof(struct SerialSettings)))
IsNew = TRUE;
else
IsNew = FALSE;
}
/* Any changes in the serial configuration area? */
if(IsNew)
{
BYTE SameDevice = TRUE;
/* Any new data to swap in? */
if(SerialConfig)
{
/* Store the previous settings. */
SaveConfig(Config,PrivateConfig);
/* Install the new settings. */
memcpy(Config -> SerialConfig,SerialConfig,sizeof(struct SerialSettings));
}
/* Any device name or unit number change? */
if(strcmp(PrivateConfig -> SerialConfig -> SerialDevice,Config -> SerialConfig -> SerialDevice) || PrivateConfig -> SerialConfig -> UnitNumber != Config -> SerialConfig -> UnitNumber)
SameDevice = FALSE;
else
{
/* Handshaking mode changed to RTS/CTS protocol? */
if((PrivateConfig -> SerialConfig -> HandshakingProtocol == HANDSHAKING_NONE && Config -> SerialConfig -> HandshakingProtocol != HANDSHAKING_NONE) || (PrivateConfig -> SerialConfig -> HandshakingProtocol != HANDSHAKING_NONE && Config -> SerialConfig -> HandshakingProtocol == HANDSHAKING_NONE))
SameDevice = FALSE;
}
/* Stop any IO activity. */
if(ReadRequest)
ClearSerial();
else
SameDevice = FALSE;
/* No dramatic changes? Simply change the parameters. */
if(SameDevice)
{
LONG Error;
if(PrivateConfig -> SerialConfig -> SerialBufferSize != Config -> SerialConfig -> SerialBufferSize)
{
STRPTR NewReadBuffer;
if(NewReadBuffer = AllocVec(Config -> SerialConfig -> SerialBufferSize,MEMF_ANY))
{
STRPTR NewStripBuffer;
if(NewStripBuffer = AllocVec(Config -> SerialConfig -> SerialBufferSize,MEMF_ANY))
{
FreeVec(ReadBuffer);
FreeVec(StripBuffer);
ReadBuffer = NewReadBuffer;
StripBuffer = NewStripBuffer;
}
else
{
FreeVec(NewReadBuffer);
Config -> SerialConfig -> SerialBufferSize = PrivateConfig -> SerialConfig -> SerialBufferSize;
}
}
else
Config -> SerialConfig -> SerialBufferSize = PrivateConfig -> SerialConfig -> SerialBufferSize;
}
/* Use new parameters... */
SetFlags(WriteRequest);
SetFlags(ReadRequest);
/* ...and set them. */
WriteRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
ReadRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
if(!(Error = DoIO(WriteRequest)))
Error = DoIO(ReadRequest);
/* Trouble? */
if(Error)
{
STRPTR String;
BYTE Reset;
/* Query the error message. */
if(!(String = GetSerialError(Error,&Reset)))
String = LocaleString(MSG_SERIAL_ERROR_DEVBUSY_TXT);
/* Build the device name/unit number string. */
SPrintf(SharedBuffer,String,Config -> SerialConfig -> SerialDevice,Config -> SerialConfig -> UnitNumber);
/* Display the error requester. */
BlockWindow(Window);
MyEasyRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),SharedBuffer);
ReleaseWindow(Window);
/* Is a serial driver reset required? */
if(Reset)
{
/* Execute the reset command. */
WriteRequest -> IOSer . io_Command = CMD_RESET;
DoIO(WriteRequest);
/* Copy the serial driver settings
* to the global configuration.
*/
GetFlags(Config,WriteRequest);
/* Also set the read request driver
* flags.
*/
SetFlags(ReadRequest);
ReadRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
DoIO(ReadRequest);
}
}
/* Restart read request. */
ReadRequest -> IOSer . io_Command = CMD_READ;
ReadRequest -> IOSer . io_Data = ReadBuffer;
ReadRequest -> IOSer . io_Length = 1;
ClrSignal(SIG_SERIAL);
SendIO(ReadRequest);
}
else
{
STRPTR Error;
/* Shut down the serial driver. */
DeleteSerial();
/* Reinitialize the serial driver. */
if(!(Error = CreateSerial()))
{
/* Free the work buffer. */
if(StripBuffer)
FreeVec(StripBuffer);
/* Try to allocate a new serial data work buffer. */
if(!(StripBuffer = (STRPTR)AllocVec(Config -> SerialConfig -> SerialBufferSize,MEMF_ANY)))
Error = LocaleString(MSG_GLOBAL_NO_AUX_BUFFERS_TXT);
}
/* Trouble? */
if(Error)
{
/* Display the error requester. */
BlockWindow(Window);
MyEasyRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),Error);
/* Clean up the mess :-( */
DeleteSerial();
ReleaseWindow(Window);
Success = RECONFIGURE_FAILURE;
}
else
{
/* Are we to display an error message? */
if(SerialMessage)
{
MyEasyRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),SerialMessage);
SerialMessage = NULL;
}
}
}
}
return(Success);
}
/* ReopenSerial():
*
* Reopen the serial driver.
*/
VOID
ReopenSerial()
{
BYTE SerialClosed = TRUE;
STRPTR Error;
do
{
if(Error = CreateSerial())
{
DeleteSerial();
switch(MyEasyRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_TERMMAIN_RETRY_IGNORE_QUIT_TXT),Error))
{
case 2: SerialClosed = FALSE;
break;
case 0: MainTerminated = TRUE;
break;
}
}
else
{
SerialClosed = FALSE;
if(SerialMessage)
{
MyEasyRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),SerialMessage);
SerialMessage = NULL;
}
}
}
while(SerialClosed);
}
/* HandleSerial():
*
* Handle the data coming in from the serial line.
*/
BYTE
HandleSerial()
{
BYTE MoreData = FALSE;
if(ReadPort && !ReleaseSerial && Status != STATUS_HOLDING)
{
if(HostReadBuffer)
{
LONG Length = XProtocolHostMon(XprIO,HostReadBuffer,0,Config -> SerialConfig -> SerialBufferSize);
if(Length)
{
if(Marking)
DropMarker();
ClearCursor();
ConProcess(HostReadBuffer,Length);
if(Status == STATUS_HOLDING)
{
DrawCursor();
return(FALSE);
}
}
MoreData = TRUE;
}
if(DataHold)
{
if(DataSize > 0)
{
register STRPTR Data = DataHold;
register LONG Size = DataSize;
DataHold = NULL;
DataSize = 0;
if(Marking)
DropMarker();
ClearCursor();
(* ConTransfer)(Data,Size);
DrawCursor();
MoreData = TRUE;
}
else
DataHold = NULL;
RestartSerial();
return(MoreData);
}
/* Any news? */
if(CheckIO(ReadRequest))
{
MoreData = TRUE;
if(!WaitIO(ReadRequest))
{
if(Marking)
DropMarker();
ClearCursor();
BytesIn++;
(* ConTransfer)(ReadBuffer,1);
if(Status != STATUS_HOLDING && !DataHold)
{
ULONG Length;
/* Check how many bytes are still in
* the serial buffer.
*/
WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
DoIO(WriteRequest);
if(Length = WriteRequest -> IOSer . io_Actual)
{
ULONG Max = Config -> SerialConfig -> SerialBufferSize;
if(Max > Config -> SerialConfig -> Quantum)
Max = Config -> SerialConfig -> Quantum;
if(Length > Max)
Length = Max;
ReadRequest -> IOSer . io_Command = CMD_READ;
ReadRequest -> IOSer . io_Data = ReadBuffer;
ReadRequest -> IOSer . io_Length = Length;
if(!DoIO(ReadRequest))
{
BytesIn += Length;
(* ConTransfer)(ReadBuffer,Length);
}
}
}
DrawCursor();
}
if(DataHold)
ClrSignal(SIG_SERIAL);
else
RestartSerial();
}
}
return(MoreData);
}